#ifndef _H_C_SPIN_LOCK_H_
#define _H_C_SPIN_LOCK_H_

#include "../typedefine.h"
#include <atomic>
#include <thread>

namespace TB
{
	class CSpinLockFlag final
	{
		NON_COPYABLE(CSpinLockFlag)
		NON_MOVEABLE(CSpinLockFlag)
	public:
		CSpinLockFlag() {}
	private:
		friend class CSpinLock;
		std::atomic_flag m_oFlag = ATOMIC_FLAG_INIT;
	};

	class CSpinLock final
	{
        NON_COPYABLE(CSpinLock)
        NON_MOVEABLE(CSpinLock)
	public:
		CSpinLock(CSpinLockFlag& oSpinLockFlag, bool bNonBlocking = false):
			m_roSpinLockFlag(oSpinLockFlag)
		{
			if (bNonBlocking) [[unlikely]]
			{
				m_bIsLockFlagOwner = !m_roSpinLockFlag.m_oFlag.test_and_set(std::memory_order_acquire);
			}
			else
			{
				while (m_roSpinLockFlag.m_oFlag.test_and_set(std::memory_order_acquire))
					std::this_thread::yield();
				m_bIsLockFlagOwner = true;
			}
		}
		~CSpinLock()
		{
			if (m_bIsLockFlagOwner)
				m_roSpinLockFlag.m_oFlag.clear(std::memory_order_release);
		}

		inline bool IsLockFlagOwner() const
		{
			return m_bIsLockFlagOwner;
		}

	private:
		CSpinLockFlag& m_roSpinLockFlag;
		bool m_bIsLockFlagOwner = false;
	};
}

#endif
